﻿using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ZXing;

namespace XUCore.NetCore
{
    public class QrCodeHelper
    {
        /// <summary>
        /// 生成扫一扫二维码
        /// </summary>
        /// <param name="size">二维码大小 px</param>
        /// <param name="url">扫描后跳转的URL地址</param>
        /// <param name="imageProcess">生成二维码后图片操作，可以合并logo</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task<byte[]> GenerateAsync(int size, string url, Action<IImageProcessingContext> imageProcess = null, CancellationToken cancellationToken = default)
        {
            size = size <= 0 ? 800 : size;

            var stream = GenerateAsync(
                value: url,
                barcodeFormat: "QR_CODE",
                width: size,
                height: size
            );

            using var proc = await Image.LoadAsync(new MemoryStream(stream), cancellationToken: cancellationToken);

            using var backgroup = new Image<Rgba32>(size, size);

            backgroup.Mutate(c =>
            {
                c.BackgroundColor(Color.White);

                c.DrawImage(proc, 1);

                imageProcess?.Invoke(c);
            });

            using var ms = new MemoryStream();

            backgroup.Save(ms, new PngEncoder());

            return ms.ToArray();
        }
        /// <summary>
        /// 生成二维码
        /// </summary>
        /// <param name="value">value</param>
        /// <param name="barcodeFormat">生成的类型 CODE_39/ CODE_93/ CODE_128/ QR_CODE   ....</param>
        /// <param name="width">二维码宽，默认500</param>
        /// <param name="height">二维码高，默认500</param>
        private static byte[] GenerateAsync(string value, string barcodeFormat, int width = 800, int height = 800)
        {
            var barcodeFormatType = (ZXing.BarcodeFormat)System.Enum.Parse(typeof(ZXing.BarcodeFormat), barcodeFormat);
            var writer = new ZXing.ImageSharp.BarcodeWriter<Rgba32>
            {
                Format = barcodeFormatType,
                Options = new ZXing.QrCode.QrCodeEncodingOptions
                {
                    DisableECI = true,
                    CharacterSet = "UTF-8",
                    Width = width,
                    Height = height,
                    Margin = 1
                }
            };

            using var image = writer.WriteAsImageSharp<Rgba32>(value);

            using var ms = new MemoryStream();
            image.Save(ms, new PngEncoder());

            return ms.ToArray();
        }
    }
}
